////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_FUNCTIONS_INL__
#define __WN_FUNCTIONS_INL__

#include "WNCore/inc/WNBase.h"
#include "WNCore/inc/WNMacros.h"

#ifdef _WN_WINDOWS
    #include <conio.h>
#elif defined _WN_LINUX
    #include <termios.h>
    #include <unistd.h>
    #include <stdio.h>
#endif

__WN_INLINE WN_BOOL WNIsMultipleOfTwo(WN_UINT64 _x) {
    return((_x % 2) == 0);
}

__WN_INLINE WN_BOOL WNIsPowerOfTwo(WN_UINT64 _x) {
    return((_x != 0) && ((_x & (~_x + 1)) == _x));
}

__WN_INLINE WN_VOID WNPauseConsole() {
    WN_PRINTF("\nPress any key to continue...");

    WN_UINT32 character;

    do {
        #ifdef _WN_WINDOWS
            character = _getch();
        #elif defined _WN_LINUX
            struct termios oldt, newt;

            tcgetattr(STDIN_FILENO, &oldt);

            newt = oldt;
            newt.c_lflag &= ~(ICANON | ECHO);

            tcsetattr(STDIN_FILENO, TCSANOW, &newt);

            character = getchar();

            tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
        #endif
    } while (character == EOF);
}

#ifdef _WN_CPLUSPLUS
    template <typename T>
    __WN_INLINE WN_BOOL WNIsValid(T _value) {
        WN_UNUSED_ARG(_value);

        return(WN_TRUE);
    }

    template <WN_VOID*>
    __WN_INLINE WN_BOOL WNIsValid(WN_VOID* _value) {
        return(_value != WN_NULL);
    }

    template <WN_CHAR*>
    __WN_INLINE WN_BOOL WNIsValid(WN_CHAR* _value) {
        return(_value != WN_NULL);
    }

    template <WN_UINT32>
    __WN_INLINE WN_BOOL WNIsValid(WN_UINT8 _value) {
        return(_value != WN_UINT8(-1));
    }

    template <WN_UINT16>
    __WN_INLINE WN_BOOL WNIsValid(WN_UINT16 _value) {
        return(_value != WN_UINT16(-1));
    }

    template <WN_UINT32>
    __WN_INLINE WN_BOOL WNIsValid(WN_UINT32 _value) {
        return(_value != WN_UINT32(-1));
    }

    template <WN_UINT64>
    __WN_INLINE WN_BOOL WNIsValid(WN_UINT64 _value) {
        return(_value != WN_UINT64(-1));
    }
#endif

#endif // __WN_FUNCTIONS_INL__
